﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.Collections;
using Pixysoft.Framework.Configurations.Core;
using System.Xml.Serialization;
using Pixysoft.Framework.Verifications;

namespace Pixysoft.Framework.Configurations.Controller
{
    /// <summary>
    /// 不支持值类型的array、所有的范型集合、值类型
    /// </summary>
    partial class ReflectionController
    {
        private static volatile ReflectionController instance;

        private static object syncRoot = new Object();

        public static ReflectionController Instance
        {
            get
            {
                if (instance == null)
                {
                    lock (syncRoot)
                    {
                        instance = new ReflectionController();
                    }
                }

                return instance;

            }
        }



        /// <summary>
        /// 支持mock模式下的pojo反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        internal T PojoDeserialize<T>(IXmlNode value)
        {
            Type objtype = typeof(T);

            object obj = PojoDeserialize(objtype, value);

            if (obj == null)
                return default(T);

            return (T)obj;
        }

        internal object PojoDeserialize(Type objectType, IXmlNode value)
        {
            switch (Pixysoft.Tools.ParserHelper.GetPropertyType(objectType))
            {
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                    {
                        break;
                    }


                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.ValueList:
                    {
                        Type listObjectType = objectType.GetGenericArguments()[0];

                        IList listObjectValue = Activator.CreateInstance(objectType) as IList;

                        foreach (IXmlNode subvalue in value.Nodes)
                        {
                            listObjectValue.Add(PojoDeserialize(listObjectType, subvalue));
                        }

                        return listObjectValue;
                    }

                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.ObjectArray:
                    {
                        Type arrayObjectType = objectType.GetElementType();

                        Array arrayObjectValue = Array.CreateInstance(arrayObjectType, value.Nodes.Count);

                        int counter = 0;

                        foreach (IXmlNode subvalue in value.Nodes)
                        {
                            arrayObjectValue.SetValue(PojoDeserialize(arrayObjectType, subvalue), counter++);
                        }

                        return arrayObjectValue;
                    }

                case DotNetPropertyType.Binary:
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                case DotNetPropertyType.Unknown:
                default:
                    {
                        return Deserialize(objectType, value);
                    }
            }


            object objectValue = null;

            if (objectType.IsInterface)
                objectValue = Pixysoft.Tools.PojoHelper.GetPojo(objectType);
            else
                objectValue = Activator.CreateInstance(objectType);

            if (objectValue == null)
                return null;

            //主动取值策略

            foreach (PropertyInfo propertyinfo in objectType.IsInterface ?
                Pixysoft.Reflection.ReflectHelper.Instance.GetInterfaceProperties(objectType) :
                objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (Pixysoft.Reflection.ReflectHelper.Instance.IsIndexProperty(propertyinfo))
                    continue;

                //10-04-22 针对attribute问题

                if (Pixysoft.Reflection.ReflectHelper.Instance.IsAttributeProperty(propertyinfo))
                    continue;

                PropertyStructure property = new PropertyStructure();

                property.SetProperty(objectValue, propertyinfo);

                if (property.IsIgnore)
                    continue;

                if (property.HasPropertyAttribute)
                {
                    GetPropertyValueByPropertyAttribute(value, objectValue, property, property);
                }
                else
                {
                    GetPojoPropertyValue(value, objectValue, property, property);
                }
            }

            return objectValue;
        }

        private void GetPojoPropertyValue(IXmlNode value, object obj, PropertyStructure property, PropertyStructure iproperty)
        {
            if (!property.PropertyInfo.CanWrite)
                return;

            switch (property.DotnetPropertyType)
            {
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                case DotNetPropertyType.Interface:
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Binary:
                    {
                        if (!value.Nodes.Contains(iproperty.PropertyName))
                            return;

                        IXmlNode childvalue = value.Node[iproperty.PropertyName];

                        object child = PojoDeserialize(property.PropertyType, childvalue);

                        if (child == null)
                            return;

                        property.PropertyInfo.SetValue(obj, child, null);

                        break;
                    }
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.ValueList:
                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.ObjectArray:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.BinaryList:
                    {
                        if (!value.Nodes.Contains(string.Format(default_format_element_arrayof, iproperty.PropertyName)))
                            return;

                        IXmlNode childvalue = value.Node[string.Format(default_format_element_arrayof, iproperty.PropertyName)];

                        object child = PojoDeserialize(property.PropertyType, childvalue);

                        if (child == null)
                            return;

                        property.PropertyInfo.SetValue(obj, child, null);

                        break;
                    }

                case DotNetPropertyType.Unknown:
                default:
                    {
                        //目前不支持集合里面是集合，例如List<byte[]>

                        break;
                    }
            }
        }



        /// <summary>
        /// 反序列化为对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="value"></param>
        /// <returns></returns>
        internal object Deserialize(Type objectType, IXmlNode value)
        {
            switch (Pixysoft.Tools.ParserHelper.GetPropertyType(objectType))
            {
                case DotNetPropertyType.Binary:
                    {
                        if (string.IsNullOrEmpty(value.Text))
                            return null;

                        byte[] binaryObjectValue = null;

                        binaryObjectValue = Pixysoft.Security.Base64.XDecript(value.Text);

                        binaryObjectValue = Pixysoft.IO.Compressor.Instance.DeCompress(binaryObjectValue);

                        return binaryObjectValue;
                    }


                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                    {
                        break;
                    }

                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.ValueList:
                    {
                        Type listObjectType = objectType.GetGenericArguments()[0];

                        IList listObjectValue = Activator.CreateInstance(objectType) as IList;

                        foreach (IXmlNode subvalue in value.Nodes)
                        {
                            listObjectValue.Add(Deserialize(listObjectType, subvalue));
                        }

                        return listObjectValue;
                    }

                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.ObjectArray:
                    {
                        Type arrayObjectType = objectType.GetElementType();

                        Array arrayObjectValue = Array.CreateInstance(arrayObjectType, value.Nodes.Count);

                        int counter = 0;

                        foreach (IXmlNode subvalue in value.Nodes)
                        {
                            arrayObjectValue.SetValue(Deserialize(arrayObjectType, subvalue), counter++);
                        }

                        return arrayObjectValue;
                    }

                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                    {
                        if (string.IsNullOrEmpty(value.Text))
                            return Pixysoft.Tools.ParserHelper.GetNullValue(objectType);

                        object objectvalue;
                        if (!Pixysoft.Tools.ParserHelper.TryParse(objectType, value.Text, out objectvalue, null))
                            throw new Exception("unknown object value. " + value.Text);
                        return objectvalue;
                    }

                case DotNetPropertyType.Unknown:
                default:
                    throw new Exception("unknown object type.");
            }

            if (objectType.IsInterface)
                throw Exceptions.UnexpectedResultException("deserialize do not support interface:{0}", objectType.Name);

            if (objectType == null)
                return null;

            if (IsInheritantFromSerializable(objectType))
            {
                return Pixysoft.IO.XmlImporter.Instance.XmlDeserialize(value.Serialize(), objectType);
            }

            object objectValue = Activator.CreateInstance(objectType);

            if (objectValue == null)
                return null;

            //主动取值策略

            foreach (PropertyInfo propertyinfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (Pixysoft.Reflection.ReflectHelper.Instance.IsIndexProperty(propertyinfo))
                    continue;

                //10-04-22 针对attribute问题

                if (Pixysoft.Reflection.ReflectHelper.Instance.IsAttributeProperty(propertyinfo))
                    continue;

                PropertyStructure property = new PropertyStructure();

                property.SetProperty(objectValue, propertyinfo);

                if (property.IsIgnore)
                    continue;

                if (property.HasPropertyAttribute)
                {
                    GetPropertyValueByPropertyAttribute(value, objectValue, property, property);
                }
                else
                {
                    GetPropertyValue(value, objectValue, property, property);
                }
            }

            return objectValue;
        }

        private void GetPropertyValue(IXmlNode value, object objectValue, PropertyStructure property, PropertyStructure iproperty)
        {
            if (!property.PropertyInfo.CanWrite)
                return;

            switch (property.DotnetPropertyType)
            {
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Binary:
                    {
                        if (!value.Nodes.Contains(iproperty.PropertyName))
                            return;

                        IXmlNode childValue = value.Node[iproperty.PropertyName];

                        object childObjectValue = Deserialize(property.PropertyType, childValue);

                        if (childObjectValue == null)
                            return;

                        property.PropertyInfo.SetValue(objectValue, childObjectValue, null);

                        break;
                    }

                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.ValueList:
                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.ObjectArray:
                    {
                        string propertyName = string.Format(default_format_element_arrayof, iproperty.PropertyName);

                        if (!value.Nodes.Contains(propertyName))
                            return;

                        IXmlNode childValue = value.Node[propertyName];

                        object childObjectValue = Deserialize(property.PropertyType, childValue);

                        if (childObjectValue == null)
                            return;

                        property.PropertyInfo.SetValue(objectValue, childObjectValue, null);

                        break;
                    }

                case DotNetPropertyType.Interface:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.InterfaceArray:
                    throw Exceptions.UnexpectedResultException("deserialize do not support interface:{0}.{1}",
                        iproperty.PropertyInfo.DeclaringType.Name, iproperty.PropertyInfo.Name);

                case DotNetPropertyType.Unknown:
                default:
                    {
                        //目前不支持集合里面是集合，例如List<byte[]>

                        break;
                    }
            }
        }

        private void GetPropertyValueByPropertyAttribute(IXmlNode value, object obj, PropertyStructure property, PropertyStructure iproperty)
        {
            //应该用原property判断 不应该用接口判断

            if (!property.PropertyInfo.CanWrite)
                return;

            //if (!iproperty.PropertyInfo.CanWrite)
            //return;

            string propertyvalue = value.Properties[iproperty.AttributeName];

            if (string.IsNullOrEmpty(propertyvalue))
                return;

            object outpropertyvalue = null;

            if (!Pixysoft.Tools.ParserHelper.TryParse(property.PropertyType, propertyvalue, out outpropertyvalue, null))
                return;

            switch (iproperty.DotnetPropertyType)
            {
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                    {
                        property.PropertyInfo.SetValue(obj, outpropertyvalue, null);

                        break;
                    }
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                case DotNetPropertyType.Binary:
                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.ObjectArray:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.ValueList:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.Unknown:
                default:
                    {
                        throw new Exception(
                            string.Format("xml property mark do not support non-value type. propertyname={0},xmlfieldname={1}",
                            property.PropertyName, iproperty.AttributeName));
                    }
            }
        }



        /// <summary> 
        /// 序列化 接口、类
        /// 不支持值类型、值类型的集合、
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        internal XmlNode Serialize(object value)
        {
            if (value == null)
                return null;

            Type objectType = value.GetType();

            XmlNode root = null;

            switch (Pixysoft.Tools.ParserHelper.GetPropertyType(objectType))
            {
                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.ValueList:
                    {
                        Type arrayObjectType = objectType.GetGenericArguments()[0];

                        root = new XmlNode(string.Format(default_format_element_arrayof, arrayObjectType.Name));

                        foreach (object subValue in value as IList)
                        {
                            root.Nodes.Add(Serialize(subValue));
                        }

                        return root;
                    }

                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.ObjectArray:
                    {
                        Type arrayObjectType = objectType.GetElementType();

                        root = new XmlNode(string.Format(default_format_element_arrayof, arrayObjectType.Name));

                        foreach (object subValue in value as IList)
                        {
                            root.Nodes.Add(Serialize(subValue));
                        }

                        return root;
                    }

                case DotNetPropertyType.Binary:
                    {
                        Type arrayObjectType = objectType.GetElementType();

                        root = new XmlNode(arrayObjectType.Name);

                        byte[] binaryValue = value as byte[];

                        binaryValue = Pixysoft.IO.Compressor.Instance.Compress(binaryValue);

                        root.Text = Pixysoft.Security.Base64.XEncript(binaryValue);

                        return root;
                    }


                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                    {
                        break;
                    }

                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                    {
                        root = new XmlNode(objectType.Name);
                        root.Text = GetStringValueByType(objectType, value);
                        return root;
                    }

                case DotNetPropertyType.Unknown:
                default:
                    throw new Exception("unknown object type.");
            }

            root = new XmlNode(GetRootName(objectType));

            //root = new XmlNode(objectType.Name);

            if (IsInheritantFromSerializable(objectType))
            {
                string xmlObjectValue = Pixysoft.IO.XmlExporter.Instance.XmlSerialize(value);

                return XmlNodeController.Instance.DeserializeToNode(Pixysoft.StringCoder.StringToByte(xmlObjectValue)) as XmlNode;
            }

            foreach (PropertyInfo propertyinfo in objectType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                if (Pixysoft.Reflection.ReflectHelper.Instance.IsIndexProperty(propertyinfo))
                    continue;

                //10-04-22 针对attribute问题

                if (Pixysoft.Reflection.ReflectHelper.Instance.IsAttributeProperty(propertyinfo))
                    continue;

                PropertyStructure property = new PropertyStructure();

                property.SetProperty(value, propertyinfo);

                if (property.IsIgnore)
                    continue;

                if (property.HasPropertyAttribute)
                {
                    SetPropertyValueByPropertyAttribute(root, property, property);
                }
                else
                {
                    SetPropertyValue(root, property, property);
                }
            }

            return root;
        }

        /// <summary>
        /// 结合接口的信息序列化对象
        /// </summary>
        /// <param name="root"></param>
        /// <param name="property"></param>
        /// <param name="iproperty"></param>
        private void SetPropertyValue(XmlNode root, PropertyStructure property, PropertyStructure iproperty)
        {
            if (property.PropertyValue == null)
                return;

            switch (property.DotnetPropertyType)
            {
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                case DotNetPropertyType.Binary:
                    {
                        XmlNode childNode = Serialize(property.PropertyValue);

                        if (childNode == null)
                            return;

                        childNode.ElementName = iproperty.PropertyName;

                        root.Nodes.Add(childNode);

                        break;
                    }

                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueList:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.ObjectArray:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.BinaryList:
                    {
                        //由于使用了递归，直接改变了xml传输的格式。导致出错。旧版本无法解析

                        XmlNode childNode = Serialize(property.PropertyValue);

                        if (childNode == null)
                            return;

                        childNode.ElementName = string.Format(default_format_element_arrayof, iproperty.PropertyName);

                        //10-04-17 为了兼容旧版本 

                        foreach (XmlNode subChildNode in childNode.Nodes)
                        {
                            subChildNode.ElementName = iproperty.PropertyName;
                        }

                        root.Nodes.Add(childNode);

                        break;
                    }

                case DotNetPropertyType.Unknown:
                default:
                    {
                        //目前不支持集合里面是集合，例如List<byte[]>

                        break;
                    }
            }
        }

        /// <summary>
        /// 根据接口定义设置值
        /// </summary>
        /// <param name="root"></param>
        /// <param name="property"></param>
        /// <param name="iproperty"></param>
        private void SetPropertyValueByPropertyAttribute(XmlNode root, PropertyStructure property, PropertyStructure iproperty)
        {
            switch (iproperty.DotnetPropertyType)
            {
                case DotNetPropertyType.Enum:
                case DotNetPropertyType.Value:
                    {
                        if (string.IsNullOrEmpty(property.PropertyStringValue))
                            break;

                        root.Properties.Add(iproperty.AttributeName, property.PropertyStringValue);

                        break;
                    }
                case DotNetPropertyType.Object:
                case DotNetPropertyType.Interface:
                case DotNetPropertyType.Binary:
                case DotNetPropertyType.EnumArray:
                case DotNetPropertyType.ValueArray:
                case DotNetPropertyType.ObjectArray:
                case DotNetPropertyType.InterfaceArray:
                case DotNetPropertyType.BinaryList:
                case DotNetPropertyType.EnumList:
                case DotNetPropertyType.ValueList:
                case DotNetPropertyType.ObjectList:
                case DotNetPropertyType.InterfaceList:
                case DotNetPropertyType.Unknown:
                default:
                    {
                        throw new Exception(
                            string.Format("xml property mark do not support non-value type. propertyname={0},xmlfieldname={1}",
                            property.PropertyName, iproperty.AttributeName));
                    }
            }
        }

        /// <summary>
        /// 是否继承只可序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        private bool IsInheritantFromSerializable(Type type)
        {
            foreach (Type itype in type.GetInterfaces())
            {
                if (string.Equals(Pixysoft.Reflection.ReflectHelper.Instance.RegularTypeName(itype),
                    Pixysoft.Reflection.ReflectHelper.Instance.RegularTypeName(typeof(System.Runtime.Serialization.ISerializable))))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 根据类型返回结果 特别针对值类型
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        private static string GetStringValueByType(Type type, object value)
        {
            if (value == null)
                return null;

            switch (Pixysoft.Tools.ParserHelper.GetDataTypeByType(type))
            {
                case DotNetDataType.Char:
                    {
                        if (value.Equals(Char.MinValue) || value.Equals(Char.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Decimal:
                    {
                        if (value.Equals(Decimal.MinValue) || value.Equals(Decimal.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Double:
                    {
                        if (value.Equals(Double.MinValue) || value.Equals(Double.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Int32:
                    {
                        if (value.Equals(Int32.MinValue) || value.Equals(Int32.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Int64:
                    {
                        if (value.Equals(Int64.MinValue) || value.Equals(Int64.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Single:
                    {
                        if (value.Equals(Single.MinValue) || value.Equals(Single.MaxValue))
                            return null;

                        return value.ToString().Trim();
                    }
                case DotNetDataType.Byte:
                case DotNetDataType.DateTime:
                case DotNetDataType.Boolean:
                case DotNetDataType.Object:
                case DotNetDataType.String:
                case DotNetDataType.UNKNOWN:
                default:
                    return value.ToString().Trim();
            }
        }

        /// <summary>
        /// 取得根节点名称
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        private static string GetRootName(Type type)
        {
            foreach (object attributeValue in type.GetCustomAttributes(typeof(XmlRootAttribute), true))
            {
                if (!(attributeValue is XmlRootAttribute))
                    continue;

                XmlRootAttribute rootValue = attributeValue as XmlRootAttribute;

                if (string.IsNullOrEmpty(rootValue.ElementName))
                    return type.Name;

                return rootValue.ElementName.Trim();
            }

            foreach (Type interfaceType in type.GetInterfaces())
            {
                foreach (object attributeValue in interfaceType.GetCustomAttributes(typeof(XmlRootAttribute), true))
                {
                    if (!(attributeValue is XmlRootAttribute))
                        continue;

                    XmlRootAttribute rootValue = attributeValue as XmlRootAttribute;

                    if (string.IsNullOrEmpty(rootValue.ElementName))
                        return type.Name;

                    return rootValue.ElementName.Trim();
                }
            }

            return type.Name;
        }
    }

    partial class ReflectionController
    {
        private const string default_format_element_arrayof = "ArrayOf{0}";

        /// <summary>
        /// 接口的结构描述
        /// </summary>
        struct PropertyStructure
        {
            //base info

            string propertyName;

            Type propertyType;

            PropertyInfo propertyInfo;

            DotNetPropertyType dotnetPropertyType;

            string propertyStringValue;

            object propertyValue;


            // manual info

            bool hasPropertyAttribute;

            string attributeName;

            bool isIgnore;


            /// <summary>
            /// 设置结构+数值 用于反序列化
            /// </summary>
            /// <param name="obj"></param>
            /// <param name="info"></param>
            public void SetProperty(Object obj, PropertyInfo info)
            {
                SetProperty(info);

                try
                {
                    propertyValue = info.GetValue(obj, null);
                }
                catch
                {
                }


                this.PropertyStringValue = ReflectionController.GetStringValueByType(propertyType, propertyValue);
            }

            private void SetProperty(PropertyInfo info)
            {
                this.propertyType = info.PropertyType;

                this.dotnetPropertyType = Pixysoft.Tools.ParserHelper.GetPropertyType(propertyType);

                this.PropertyInfo = info;


                // element mapping

                XmlElementAttribute[] elementsattributes = info.GetCustomAttributes(
                    typeof(XmlElementAttribute), true) as XmlElementAttribute[];

                if (elementsattributes == null || elementsattributes.Length == 0)
                {
                    this.propertyName = info.Name;
                }
                else if (string.IsNullOrEmpty(elementsattributes[0].ElementName))
                {
                    this.propertyName = info.Name;
                }
                else
                {
                    this.propertyName = elementsattributes[0].ElementName.Trim();
                }




                // property mapping

                XmlAttributeAttribute[] propertyattributes = info.
                            GetCustomAttributes(typeof(XmlAttributeAttribute), true) as XmlAttributeAttribute[];

                if (propertyattributes == null || propertyattributes.Length == 0)
                {
                    this.hasPropertyAttribute = false;
                }
                else
                {
                    this.hasPropertyAttribute = true;

                    this.AttributeName = propertyattributes[0].AttributeName;
                }


                //ignore mapping

                object[] ignores = info.GetCustomAttributes(typeof(XmlIgnoreAttribute), true);

                if (ignores != null && ignores.Length > 0)
                    this.IsIgnore = true;
                else
                    this.isIgnore = false;
            }


            public T GetPropetyValue<T>()
            {
                return (T)propertyValue;
            }

            public string PropertyStringValue
            {
                get { return propertyStringValue; }
                set { propertyStringValue = value; }
            }

            public object PropertyValue
            {
                get { return propertyValue; }
                set { propertyValue = value; }
            }


            public string PropertyName
            {
                get { return propertyName; }
                set { propertyName = value; }
            }

            public Type PropertyType
            {
                get { return propertyType; }
                set { propertyType = value; }
            }

            public PropertyInfo PropertyInfo
            {
                get { return propertyInfo; }
                set { propertyInfo = value; }
            }

            public DotNetPropertyType DotnetPropertyType
            {
                get { return dotnetPropertyType; }
                set { dotnetPropertyType = value; }
            }


            /// <summary>
            /// whether has XmlAttributeAttribute
            /// </summary>
            public bool HasPropertyAttribute
            {
                get { return hasPropertyAttribute; }
                set { hasPropertyAttribute = value; }
            }

            /// <summary>
            /// value of XmlAttributeAttribute 
            /// </summary>
            public string AttributeName
            {
                get { return attributeName; }
                set { attributeName = value; }
            }

            /// <summary>
            /// whether has Ignore Attribute
            /// </summary>
            public bool IsIgnore
            {
                get { return isIgnore; }
                set { isIgnore = value; }
            }
        }
    }

}
